/**

   File.c
   ======

   File management

**/



/**

   Includes
   --------
   
   - stdlib     :  malloc, free
   - stdint.h   :  uintX_t
   - pthread.h  :  threads
   - bitfield.h :  bitfield management
   - huffman.h  :  huffman code
   - chunk.h    :  chunk
   - file.h     :  self header

**/


#include <stdlib.h>
#include <stdint.h>
#include <pthread.h>
#include <bitfield.h>
#include "huffman.h"
#include "chunk.h"
#include "file.h"




/**

   Function: struct file* file_create(void)
   ----------------------------------------

   Create a empty file

**/

struct file* file_create(char* name, struct huff_tree* t)
{
  struct file* f;

  /* Allocate structure */
  f = (struct file*)malloc(sizeof(struct file));
  if (f == NULL)
    {
      return NULL;
    }

  /* Create bitfield */
  f->name = huff_encode(name,t);
  if (f->name == NULL)
    {
      free(f);
      return NULL;
    }

  /* Initialize lock */
  pthread_mutex_init(&(f->lock),NULL);

  /* Fill fields */
  f->nchunks = 0;
  f->offset = 0;
  f->chunks = NULL;

  /* Return */
  return f;

}





/**

   Function: int file_add_chunk(struct file* f,struct chunk* c)
   ------------------------------------------------------------

   Add a chunk to a file. Chunk will be placed at th end of the list

**/

struct chunk* file_add_chunk(struct file* f)
{
  struct chunk* c;

   if ( f == NULL )
    {
      return NULL;
    }

   /* Create chunk */
   c = chunk_create();
   if (c == NULL)
     {
       return NULL;
     }

  /* Append chunk */
  if ( f->nchunks )
    {
      struct chunk* tmp;
      
      tmp = f->chunks;
      while( tmp->next != NULL )
	{
	  tmp = tmp->next;
	}

      /* Set chunk */
      tmp->next = c;

      /* Update count */
      f->nchunks++;

    }
  else
    {
      /* Just set chunk */
      f->chunks = c;
      f->nchunks = 1;
    }

  return c;

}




/**

   Function: void file_delete(struct file* f)
   ------------------------------------------

   Delete a file

**/

void file_delete(struct file* f)
{
  if (f != NULL)
    {
      struct chunk* c;
      struct chunk* next;
      /* Free chunks */
      c = f->chunks;
      while(c)
	{
	  next = c->next;
	  chunk_delete(c);
	  c=next;
	}

      /* Free bitfield */
      bf_delete(f->name);

      /* Free structure */
      free(f);

    }

  return;
}



/**

   Function: int file_compare(struct file* f1, struct file* f2)
   ------------------------------------------------------------

   Comapre two files, according to their name

**/


int file_compare(struct file* f1, struct file* f2)
{
  if ( (f1 != NULL) && (f2 != NULL) )
    {
      return bf_compare(f1->name,f2->name);
    }

  return 0;
}
